home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr11 / ddj9304.zip / 1993-APR.ZIP / OS2WPS.ASC < prev    next >
Text File  |  1993-02-17  |  22KB  |  556 lines

  1. _PROGRAMMING FOR THE OS/2 2.0 WORKPLACE SHELL_
  2. by Joel Barnum
  3.  
  4. [LISTING ONE]
  5.  
  6. // spread.c -- a sample WPS application
  7.  
  8. #define  INCL_WIN
  9. #define  INCL_GPI
  10. #include <os2.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include "spread.h"
  14.  
  15. #define WM_INIT WM_USER
  16.  
  17. // Internal function prototypes
  18. int main ( int argc, char *argv[] );
  19. BOOL savefile ( PSZ szFname, LONG alValues[] );
  20. BOOL openfile ( PSZ szFname, LONG alValues[] );
  21. BOOL settype ( HFILE hf, PSZ pszType );
  22. MRESULT EXPENTRY ValueDlgProc ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 );
  23. MRESULT EXPENTRY ClientWinProc ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
  24. // global variables
  25.     HAB  hab;               // Anchor block handle
  26. int main ( int argc, char *argv[] )
  27. {
  28.     HMQ  hmq;               // Message queue handle
  29.     HWND hwndFrame;         // Frame window handle
  30.     HWND hwndClient;        // Client window handle
  31.     QMSG qmsg;              // Message from queue
  32.     ULONG flCreate;         // Window creation flags
  33.     BOOL  fSuccess;         // return from API
  34.     hab = WinInitialize ( 0 );
  35.     hmq = WinCreateMsgQueue ( hab, 0 );
  36.     fSuccess = WinRegisterClass (hab,"spread",ClientWinProc,CS_SIZEREDRAW,0);
  37.     flCreate = FCF_SYSMENU | FCF_SIZEBORDER | FCF_TITLEBAR |
  38.                FCF_MINMAX  | FCF_SHELLPOSITION | FCF_TASKLIST | FCF_ICON;
  39.     hwndFrame = WinCreateStdWindow ( HWND_DESKTOP, WS_VISIBLE
  40.                  , &flCreate, "spread", NULL, 0L, 0 , ID_WINDOW, &hwndClient );
  41.     if ( hwndFrame == NULLHANDLE )
  42.         DosExit ( 1, 1 );
  43.   // send the client a message passing arg count and arguments
  44.     WinSendMsg ( hwndClient, WM_INIT, MPFROMSHORT ( argc ) ,MPFROMP ( argv ));
  45.     while ( WinGetMsg ( hab, &qmsg, NULLHANDLE, 0, 0 ) != FALSE )
  46.         WinDispatchMsg  ( hab, &qmsg );
  47.     fSuccess = WinDestroyWindow ( hwndFrame );
  48.     fSuccess = WinDestroyMsgQueue ( hmq );
  49.     fSuccess = WinTerminate ( hab );
  50.     return 0;
  51. }
  52. //************************************************************
  53. MRESULT EXPENTRY ClientWinProc ( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
  54. {
  55.         BOOL    fSuccess;       // return from API
  56. static  LONG    alValues[2];    // spreadsheet values
  57. static  HWND    hwndMenu;       // popup menu handle
  58. static  CHAR    szFname[255];   // file name
  59.     switch( msg )
  60.     {
  61.         case WM_BUTTON2DOWN:
  62.             {
  63.                 POINTL  ptl;
  64.               // display a popup menu at the coordinates the user clicked
  65.                 ptl.x = SHORT1FROMMP ( mp1 );
  66.                 ptl.y = SHORT2FROMMP ( mp1 );
  67.                 WinMapWindowPoints ( hwnd, HWND_DESKTOP, &ptl, 1 );
  68.                 fSuccess = WinPopupMenu (
  69.                        HWND_DESKTOP , hwnd , hwndMenu , ptl.x , ptl.y
  70.                      , 0 , PU_KEYBOARD | PU_NONE | PU_MOUSEBUTTON1 );
  71.             }
  72.             return (MRESULT)FALSE;
  73.         case WM_CLOSE:
  74.             savefile ( szFname, alValues );
  75.             WinPostMsg( hwnd, WM_QUIT, 0L, 0L );
  76.             return (MRESULT) NULL;
  77.         case WM_COMMAND:
  78.             switch ( SHORT1FROMMP ( mp1 ) )
  79.             {
  80.                 case IDM_CHANGE:
  81.                     {
  82.                         ULONG   result;
  83.                       // display a modal dialog to let user enter in new values
  84.                         result = WinDlgBox ( HWND_DESKTOP
  85.                              , WinQueryWindow ( hwnd, QW_PARENT ), ValueDlgProc
  86.                              , NULLHANDLE , DLG_VALUES , alValues );
  87.                         if ( result == DID_OK )
  88.                             WinInvalidateRect ( hwnd, NULL, TRUE );
  89.                     }
  90.                     break;
  91.             }
  92.             return (MRESULT)NULL;
  93.         case WM_CREATE:
  94.           //load our popup menu
  95.             hwndMenu = WinLoadMenu ( HWND_DESKTOP , NULLHANDLE, ID_MENU );
  96.             return (MRESULT)FALSE;
  97.         case WM_INIT:           // user-defined message
  98.             {
  99.                 int     argc;           // argument count
  100.                 CHAR    **argv;         // input arguments
  101.                 CHAR    szTitle[255];   // titlebar text
  102.               // extract argument count and strings
  103.                 argc = SHORT1FROMMP ( mp1 );
  104.                 argv = PVOIDFROMMP  ( mp2 );
  105.               // if there were no input arguments, exit
  106.                 if ( argc < 2 )
  107.                 {
  108.                     WinMessageBox (
  109.                         HWND_DESKTOP , WinQueryWindow ( hwnd, QW_PARENT )
  110.                         , "You must specify an input file"
  111.                         , "Error", 0 , MB_OK | MB_ERROR );
  112.                     DosExit ( 1, 1 );
  113.                 }
  114.               // attempt to open input file
  115.                 strcpy ( szFname, argv[1] );
  116.                 if ( openfile ( argv[1], alValues ) == FALSE )
  117.                 {
  118.                     WinMessageBox (
  119.                              HWND_DESKTOP
  120.                             , WinQueryWindow ( hwnd, QW_PARENT ) , argv[1] 
  121.                             , "Unable to open file", 0 , MB_OK | MB_ERROR );
  122.                     DosExit ( 1, 1 );                           
  123.                 }
  124.               // update the titlebar text
  125.                 strcpy ( szTitle, "Spreadsheet  - " );
  126.                 strcat ( szTitle, szFname );
  127.                 WinSetWindowText ( WinQueryWindow ( hwnd, QW_PARENT ),szTitle);
  128.             }
  129.             return (MRESULT)NULL;
  130.         case WM_PAINT:
  131.             {
  132.                 LONG    lSuccess;       // return from API
  133.                 HPS     hps;            // cached PS
  134.                 POINTL  ptl;            // coordinates for draw
  135.                 CHAR    sz[50];         // temp string
  136.                 hps = WinBeginPaint ( hwnd , NULLHANDLE, NULL );
  137.                 fSuccess = GpiErase ( hps );
  138.               // draw the values and their sum
  139.                 ptl.x = 100; ptl.y = 125;
  140.                 _itoa ( alValues[0], sz, 10 );
  141.                 lSuccess = GpiCharStringAt ( hps, &ptl, strlen ( sz ) , sz );
  142.                 ptl.y = 100;
  143.                 _itoa ( alValues[1], sz, 10 );
  144.                 lSuccess = GpiCharStringAt ( hps, &ptl, strlen ( sz ) , sz );
  145.                 ptl.y = 75;
  146.                 lSuccess = GpiMove ( hps, &ptl );
  147.                 ptl.x = 200;
  148.                 lSuccess = GpiLine ( hps, &ptl );
  149.                 ptl.x = 100; ptl.y = 50;
  150.                 _itoa ( alValues[0] + alValues[1], sz, 10 );
  151.                 lSuccess = GpiCharStringAt ( hps, &ptl, strlen ( sz ) , sz );
  152.                 ptl.x = 50; ptl.y = 25;
  153.                 strcpy ( sz, "Press the right mouse button to change values" );
  154.                 lSuccess = GpiCharStringAt ( hps, &ptl, strlen ( sz ) , sz );
  155.                 fSuccess = WinEndPaint ( hps );
  156.             }
  157.             return (MRESULT) NULL;
  158.         default:
  159.             return
  160.                 WinDefWindowProc( hwnd, msg, mp1, mp2 );
  161.     }
  162.     return WinDefWindowProc( hwnd, msg, mp1, mp2 );
  163. }
  164. // savefile:  saves the current values to a file
  165. //      RETURNS:  TRUE if successful, FALSE if not
  166. BOOL savefile ( PSZ szFname, LONG alValues[] )
  167. {
  168.     HFILE   h;                  // file handle
  169.     ULONG   ulAction;           // action taken by OPEN
  170.     ULONG   ulActualWritten;    // count written to file
  171.     APIRET  rc;                 // return code
  172.   // open the current file
  173.     rc = DosOpen ( szFname, &h, &ulAction, 0L
  174.             , 0, OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW
  175.             , OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE, NULL );
  176.     if ( rc != 0 )
  177.         return FALSE;
  178.   // write the two values
  179.     rc = DosWrite ( h, alValues, 8, &ulActualWritten );
  180.     if ( ( rc != 0 )  || ( ulActualWritten != 8 ) )
  181.     {
  182.         DosClose ( h );
  183.         return FALSE;
  184.     }
  185.   // write our .TYPE EA on the file
  186.     settype ( h, "XX Company Spreadsheet" );
  187.   // close the file
  188.     DosClose ( h );
  189.     return TRUE;
  190. }
  191. // openfile: reads spreadsheet values from the specified file
  192. //      RETURNS:  TRUE if successful, FALSE if not
  193. BOOL openfile ( PSZ szFname, LONG alValues[] )
  194. {
  195.     HFILE   h;                  // file handle
  196.     ULONG   ulAction;           // action taken by OPEN
  197.     ULONG   ulActualRead;       // count read from file
  198.     APIRET  rc;                 // return code
  199.   // open the file
  200.     rc = DosOpen ( szFname, &h, &ulAction, 0L , 0
  201.             , OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW
  202.             , OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE , NULL );
  203.     if ( rc != 0 )
  204.         return FALSE;
  205.   // read the values
  206.     rc = DosRead ( h, alValues, 8, &ulActualRead );
  207.     if ( rc != 0 )
  208.     {
  209.         DosClose ( h );
  210.         return FALSE;
  211.     }
  212.   // zero length files are OK, but otherwise less than 8 bytes means bad file
  213.     if ( ulActualRead < 8 )
  214.         if ( ulActualRead != 0 )
  215.         {
  216.             DosClose ( h );
  217.             return FALSE;
  218.         }
  219.   // close the file
  220.     DosClose ( h );
  221.     return TRUE;
  222. }
  223. // settype: sets the .TYPE ea for a data file
  224. BOOL settype ( HFILE hf, PSZ pszType )
  225. {
  226. // define a .TYPE EA structure
  227. typedef struct _TYPEEALIST
  228. {
  229.     ULONG   cbList;         // length of all EAs in list
  230.     ULONG   ulNextEa;       // offset of next EA
  231.     BYTE    bFlags;         // EA flags
  232.     BYTE    cbName;         // length of name
  233.     USHORT  cbEA;           // sizeof EA
  234.     CHAR    szName[6];      // ".TYPE"
  235.     USHORT  usType;         // EA data type
  236.     USHORT  cbValue;        // sizeof value
  237.     CHAR    achValue[1];    // placeholder for EA value
  238. } TEALIST, *PTEALIST;
  239.     EAOP2       eaop;           // extended attributes structure
  240.     PTEALIST    ptea;           // points to TYPE EA list
  241.     PSZ         psz1, psz2;     // temp pointers
  242.     USHORT      cb;             // structure length
  243.     APIRET      rc;             // return from API
  244.   // allocate memory for the TYPE EA list
  245.   // -1 because the structure itself defines 1 char
  246.     cb = strlen ( pszType ) - 1   +
  247.          sizeof ( TEALIST );
  248.     ptea = (PTEALIST)malloc ( cb );
  249.   // initialize the EA structures
  250.   // fill in the EA value itself: for .TYPE it's the file type
  251.   // can't use strcpy!! (needs to add '\0')
  252.     psz1 = pszType;
  253.     psz2 = ptea->achValue;
  254.     while ( *psz1 != '\0' )
  255.         *psz2++ = *psz1++;
  256.   // fill in length of the EA value
  257.     ptea->cbValue = strlen ( pszType );
  258.   // fill type of EA value
  259.     ptea->usType = 0xfffd;            // length-preceded ASCII
  260.   // length of EA (includes value + type and length fields)
  261.     ptea->cbEA = ptea->cbValue + sizeof(ptea->usType) + sizeof (ptea->cbValue);
  262.   // fill in the EA name (it's a null terminated string so strcpy is OK)
  263.     strcpy ( ptea->szName, ".TYPE" );
  264.   // fill in EA name length
  265.     ptea->cbName = (BYTE)strlen ( ".TYPE" );
  266.   // point to the TYPE EA list structure
  267.     eaop.fpFEA2List = (PFEA2LIST)ptea;
  268.     eaop.fpGEA2List = NULL;
  269.     ptea->cbList = cb;                  // structure length
  270.     ptea->ulNextEa = 0;                 // no more EAs
  271.     ptea->bFlags = 0;                   // noncritical
  272.   // attach the .TYPE extended attribute to the file
  273.     rc = DosSetFileInfo ( hf, 2, (PBYTE)&eaop , sizeof (EAOP2) );
  274.     free ( ptea );
  275.     return (BOOL)rc;
  276. }
  277. MRESULT EXPENTRY ValueDlgProc ( HWND hwnd, ULONG msg , MPARAM mp1, MPARAM mp2 )
  278. {
  279. static  PLONG   alValues;
  280.     switch ( msg )
  281.     {
  282.         case WM_INITDLG:
  283.           // retrieve a pointer to values array
  284.             alValues = PVOIDFROMMP ( mp2 );
  285.           // write current values into entry fields
  286.             WinSetDlgItemShort ( hwnd, DLG_VALUE1, (SHORT)alValues[0], TRUE );
  287.             WinSetDlgItemShort ( hwnd, DLG_VALUE2, (SHORT)alValues[1], TRUE );
  288.           // set the focus to the first entryfield
  289.             WinSetFocus ( HWND_DESKTOP, WinWindowFromID ( hwnd, DLG_VALUE1 ) );
  290.             return (MRESULT)TRUE;
  291.         case WM_COMMAND:
  292.             switch ( SHORT1FROMMP ( mp1 ) )
  293.             {
  294.                 case DID_CANCEL:
  295.                     WinDismissDlg ( hwnd, DID_CANCEL );
  296.                     break;
  297.                 case DID_OK:
  298.                   // retrieve values from entry fields
  299.                     WinQueryDlgItemShort ( hwnd, DLG_VALUE1
  300.                             , (PSHORT)&alValues[0], TRUE );
  301.                     WinQueryDlgItemShort ( hwnd, DLG_VALUE2
  302.                             , (PSHORT)&alValues[1], TRUE );
  303.                     WinDismissDlg ( hwnd, DID_OK );
  304.             }
  305.             return (MRESULT)NULL;
  306.         default:
  307.             return
  308.                 WinDefDlgProc( hwnd, msg, mp1, mp2 );
  309.     }
  310.     return WinDefDlgProc( hwnd, msg, mp1, mp2 );
  311. }
  312.  
  313.  
  314. [LISTING TWO]
  315.  
  316. #include <os2.h>
  317. #include "spread.h"
  318. rcinclude spread.dlg
  319.  
  320. ICON    ID_WINDOW spread.ico
  321. MENU ID_MENU
  322. BEGIN
  323.         MENUITEM "~Change values",       IDM_CHANGE
  324. END
  325. ASSOCTABLE      1
  326. {
  327.         "XX Company Spreadsheet", "*.SPR", spread.ico
  328. }
  329.  
  330.  
  331. [LISTING THREE]
  332.  
  333. # Subclass of WPDataFile for Spreadsheet sample WPS application
  334. #include <wpdataf.sc>
  335. class:  WPSpread,
  336.         external stem = wpspread, local,
  337.         external prefix = wpspread_,
  338.         classprefix = wpspreadM_,
  339.         major version = 1,
  340.         minor version = 2;
  341. parent: WPDataFile;
  342. passthru: C.ih;
  343.    #define INCL_WIN
  344.    #define INCL_DOS
  345.    #define INCL_DEV
  346.    #define INCL_GPI
  347.    #define INCL_WPCLASS
  348.    #define INCL_WPFOLDER
  349.    #include <os2.h>
  350.    #include <stdlib.h>
  351.    #include <string.h>
  352. endpassthru;   /* .ih */
  353. data:
  354.         HPOINTER        hicon,          class;  // class icon
  355. methods:
  356.         override        wpclsQueryTitle,                class;
  357.         override        wpclsInitData,                  class;
  358.         override        wpclsQueryIcon,                 class;
  359.         override        wpclsQueryInstanceFilter,       class;
  360.         override        wpclsQueryInstanceType,         class;
  361.         override        wpPrintObject;
  362.  
  363.  
  364. [LISTING FOUR]
  365.  
  366. /* This file was generated by the SOM Compiler. FileName: wpspread.c.
  367.  * Generated using: SOM Precompiler spc: 1.22 SOM Emitter emitc: 1.24 */
  368. #define WPSpread_Class_Source
  369. #include "wpspread.ih"
  370.  
  371. BOOL openfile ( PSZ szFname, LONG alValues[] );
  372. BOOL printspread ( WPSpread *somSelf, PPRINTDEST pPrintDest );;
  373.  
  374. #undef SOM_CurrentClass
  375. #define SOM_CurrentClass SOMMeta
  376. SOM_Scope PSZ   SOMLINK wpspreadM_wpclsQueryTitle(M_WPSpread *somSelf)
  377. {
  378.     M_WPSpreadData *somThis = M_WPSpreadGetData(somSelf);
  379.     M_WPSpreadMethodDebug("M_WPSpread","wpspreadM_wpclsQueryTitle");
  380.     return _wpclsQueryInstanceType( somSelf );
  381. }
  382. SOM_Scope void   SOMLINK wpspreadM_wpclsInitData(M_WPSpread *somSelf)
  383. {
  384.     HMODULE hmod;               // module handle
  385.     PSZ     psz;                // module file name
  386.     APIRET  rc;                 // return from API
  387.     M_WPSpreadData *somThis = M_WPSpreadGetData(somSelf);
  388.     M_WPSpreadMethodDebug("M_WPSpread","wpspreadM_wpclsInitData");
  389.   // initialize the parent classes first
  390.     parent_wpclsInitData ( somSelf );
  391.   // query our module name
  392.     psz = _somLocateClassFile( SOMClassMgrObject, SOM_IdFromString( "WPChart" )
  393.                           , WPSpread_MajorVersion , WPSpread_MinorVersion );
  394.   // query our module handle
  395.     if ( psz != NULL )
  396.         rc = DosQueryModuleHandle ( psz, &hmod );
  397.   // load the icon (same as pointer) and store in class data
  398.     _hicon = WinLoadPointer ( HWND_DESKTOP, hmod, 1 );
  399. }
  400. SOM_Scope HPOINTER   SOMLINK wpspreadM_wpclsQueryIcon(M_WPSpread *somSelf)
  401. {
  402.     M_WPSpreadData *somThis = M_WPSpreadGetData(somSelf);
  403.     M_WPSpreadMethodDebug("M_WPSpread","wpspreadM_wpclsQueryIcon");
  404.     return _hicon;
  405. }
  406. SOM_Scope PSZ   SOMLINK wpspreadM_wpclsQueryInstanceFilter(M_WPSpread *somSelf)
  407. {
  408.     M_WPSpreadData *somThis = M_WPSpreadGetData(somSelf);
  409.     M_WPSpreadMethodDebug("M_WPSpread","wpspreadM_wpclsQueryInstanceFilter");
  410.     return ".SPR";
  411. }
  412. SOM_Scope PSZ   SOMLINK wpspreadM_wpclsQueryInstanceType(M_WPSpread *somSelf)
  413. {
  414.     M_WPSpreadData *somThis = M_WPSpreadGetData(somSelf);
  415.     M_WPSpreadMethodDebug("M_WPSpread","wpspreadM_wpclsQueryInstanceType");
  416.     return "XX Company Spreadsheet";
  417. }
  418. #undef SOM_CurrentClass
  419. #define SOM_CurrentClass SOMInstance
  420. SOM_Scope BOOL   SOMLINK wpspread_wpPrintObject(WPSpread *somSelf,
  421.         PPRINTDEST pPrintDest,
  422.         ULONG ulReserved)
  423. {
  424.     /* WPSpreadData *somThis = WPSpreadGetData(somSelf); */
  425.     WPSpreadMethodDebug("WPSpread","wpspread_wpPrintObject");
  426.     return printspread ( somSelf, pPrintDest );
  427. }
  428. //************* Following code NOT generated by SOM compiler
  429. // printspread: prints the file this object represents
  430. //      RETURNS:  TRUE if successful, FALSE if not
  431. BOOL printspread ( WPSpread *somSelf, PPRINTDEST pPrintDest )
  432. {
  433.     HDC     hdcPrinter;             // printer DC
  434.     HAB     hab;                    // anchor block handle
  435.     HPS     hps;                    // micro PS
  436.     SIZEL   sizel;                  // presentation page size
  437.     LONG    alValues[2];            // spreadsheet values
  438.     BOOL    fSuccess;               // return from API
  439.     BOOL    lSuccess;               // return from API
  440.     CHAR    szFname[255];           // file name
  441.     ULONG   cb;                     // filename length
  442.     POINTL  ptl;                    // drawing coordinates
  443.     CHAR    sz[50];                 // temporary string
  444.   // create a printer device context
  445.     hab = WinQueryAnchorBlock ( HWND_DESKTOP );
  446.     hdcPrinter = DevOpenDC ( hab , pPrintDest->lType
  447.                 , pPrintDest->pszToken , pPrintDest->lCount
  448.                 , pPrintDest->pdopData , NULLHANDLE );
  449.   // create a micro PS associated with the printer DC
  450.     sizel.cx = sizel.cy = 0;
  451.     hps = GpiCreatePS ( hab, hdcPrinter, &sizel
  452.             , GPIT_MICRO | PU_LOENGLISH | GPIA_ASSOC );
  453.   // open the file associated with this object
  454.     cb = 255;
  455.     _wpQueryRealName ( somSelf, szFname, &cb, TRUE );
  456.     fSuccess = openfile ( szFname , alValues );
  457.   // start a printer job
  458.     lSuccess = DevEscape ( hdcPrinter, DEVESC_STARTDOC
  459.             , strlen ( _wpQueryTitle ( somSelf ) )
  460.             , _wpQueryTitle ( somSelf ) , NULL, NULL );
  461.   // print the values
  462.     ptl.x = 100; ptl.y = 125;
  463.     _itoa ( alValues[0], sz, 10 );
  464.     lSuccess = GpiCharStringAt ( hps, &ptl, strlen ( sz ) , sz );
  465.     ptl.y = 100;
  466.     _itoa ( alValues[1], sz, 10 );
  467.     lSuccess = GpiCharStringAt ( hps, &ptl, strlen ( sz ) , sz );
  468.     ptl.y = 75;
  469.     lSuccess = GpiMove ( hps, &ptl );
  470.     ptl.x = 200;
  471.     lSuccess = GpiLine ( hps, &ptl );
  472.     ptl.x = 100; ptl.y = 50;
  473.     _itoa ( alValues[0] + alValues[1], sz, 10 );
  474.     lSuccess = GpiCharStringAt ( hps, &ptl, strlen ( sz ) , sz );
  475.   // end a printer job
  476.     lSuccess = DevEscape ( hdcPrinter, DEVESC_ENDDOC , 0 , NULL, NULL, NULL );
  477.   // clean up
  478.     DevCloseDC ( hdcPrinter );
  479.     GpiDestroyPS ( hps );
  480.     return TRUE;
  481. }
  482. // openfile: reads spreadsheet values from the specified file
  483. //      RETURNS:  TRUE if successful, FALSE if not
  484. BOOL openfile ( PSZ szFname, LONG alValues[] )
  485. {
  486.     HFILE   h;                  // file handle
  487.     ULONG   ulAction;           // action taken by OPEN
  488.     ULONG   ulActualRead;       // count read from file
  489.     APIRET  rc;                 // return code
  490.   // open the file
  491.     rc = DosOpen ( szFname, &h, &ulAction, 0L
  492.             , 0, OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW
  493.             , OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, NULL );
  494.     if ( rc != 0 )
  495.         return FALSE;
  496.   // read the values
  497.     rc = DosRead ( h, alValues, 8, &ulActualRead );
  498.     if ( ( rc != 0 )  || ( ulActualRead != 8 ) )
  499.     {
  500.         DosClose ( h );
  501.         return FALSE;
  502.     }
  503.   // close the file
  504.     DosClose ( h );
  505.     return TRUE;
  506. }
  507.  
  508.  
  509. [LISTING FIVE]
  510.  
  511. // install.c -- installation program for spreadsheet app
  512. //  compile and link with: icc /Ss /Ti install.c
  513.  
  514. #define INCL_WINWORKPLACE
  515. #include <os2.h>
  516. int main ( int argc, char *argv[] )
  517. {
  518.     HAB     hab;                    // anchor block
  519.     HOBJECT hobjFolder;             // folder object
  520.     HOBJECT hobjProg;               // program object
  521.     BOOL    fSuccess;               // return from API
  522.   // create an anchor block so we can retrieve errors
  523.     hab = WinInitialize ( 0 );
  524.   // create a folder on the desktop for our program object
  525.     hobjFolder = WinCreateObject ( "WPFolder", "My Folder" 
  526.               , "OBJECTID=<MY_FOLDER>" , "<WP_DESKTOP>" , CO_REPLACEIFEXISTS );
  527.     if ( hobjFolder == NULLHANDLE )
  528.     {
  529.         ULONG   ul;             // error code
  530.         ul = WinGetLastError ( hab );
  531.         printf ("Unable to create folder, error = %x\n", ERRORIDERROR ( ul ) );
  532.     }
  533.   // register our object class for our data files
  534.     fSuccess = WinRegisterObjectClass ( "WPSpread" , "c:\\book\\wpsart\\wpspread.dll" );
  535.     if ( fSuccess == FALSE )
  536.     {
  537.         ULONG   ul;             // error code
  538.         ul = WinGetLastError ( hab );
  539.         printf ("Unable to register class, error = %x\n", ERRORIDERROR ( ul ) );
  540.     }
  541.   // create a program object for our EXE file
  542.     hobjProg = WinCreateObject ( "WPProgram", "Spreadsheet App"
  543.                     , "EXENAME=c:\\book\\wpsart\\spread.exe;"
  544.                       "ASSOCTYPE=XX Company Spreadsheet,,;"
  545.                       "ASSOCFILTER=*.SPR,," , "<MY_FOLDER>"
  546.                     , CO_REPLACEIFEXISTS );
  547.     if ( hobjProg == NULLHANDLE )
  548.     {
  549.         ULONG   ul;             // error code
  550.         ul = WinGetLastError ( hab );
  551.         printf ("Unable to create program object, error = %x\n", ERRORIDERROR ( ul ) );
  552.     }
  553.     WinTerminate ( hab );
  554. }
  555.  
  556.